package mws;


import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;

import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public abstract class ThreadPoolConfigListener implements Listener {

    private final ThreadPoolContext threadPoolContext = ThreadPoolContext.getInstance();
    // YAML解析工具
    private final YAMLMapper yamlMapper = new YAMLMapper(); // 这是不是线程安全的

    private Object mainLock = new Object();

    // 构造注入线程池映射（实际项目中需根据你的管理方式调整）
    public ThreadPoolConfigListener() {
    }

    @Override
    public void receiveConfigInfo(String configInfo) {
        ThreadPoolConfigRoot configRoot = null;
        System.out.println("检测到配置可能更新");
        // 这个 是轮询
        try {
            // 1. 解析Nacos更新的配置为实体类
            configRoot = yamlMapper.readValue(configInfo, ThreadPoolConfigRoot.class);
        } catch (Exception e) {
            System.err.println("线程池配置更新失败：" + e.getMessage());
            e.printStackTrace();
        }
        List<ThreadPoolProperty> newConfigs = configRoot.getThreadPoolConfig().getThreadPools();

        if (newConfigs == null || newConfigs.isEmpty()) {
            System.out.println("线程池配置为空，不执行更新");
            return;
        }

        System.out.println("遍历新配置，更新对应线程池");
        // 2. 遍历新配置，更新对应线程池
        boolean reJust = false;
        ThreadPoolConfigRoot returnConfigs = ThreadPoolConfigRoot.createThreadPoolConfigRoot();
        for (ThreadPoolProperty newConfig : newConfigs) {
            if(newConfig == null){
                continue;
            }
            ThreadPoolProperty returnProperties = null;
            String poolName = newConfig.getName();
            ThreadPoolProperty oldConfig = threadPoolContext.getThreadPoolProperty(poolName);
            try {


                UPDATE_TYPE updateType = UPDATE_TYPE.NO_UPDATE;
                if (oldConfig == null) {
                    threadPoolContext.setThreadPoolProperty(poolName, newConfig);
                    updateType = UPDATE_TYPE.NEW_LIFE;
                } else if (!checkUpdateType(oldConfig, newConfig)) {
                    updateType = UPDATE_TYPE.UPDATE_OLDEST;
                }else {
                    returnProperties = oldConfig;
                }
                // 3. 动态更新可调整的参数（核心参数）
                updateThreadPool(poolName, newConfig, updateType);
                if(updateType != UPDATE_TYPE.NO_UPDATE){
                    threadPoolContext.setThreadPoolProperty(poolName,newConfig);
                    returnProperties = newConfig;
                }

            } catch (Exception exception) {
                reJust = true;
                returnProperties = oldConfig;
                System.out.println("线程池配置更新失败：" + newConfig.toString());
            }
            returnConfigs.getThreadPoolConfig().getThreadPools().add(returnProperties);
        }
        if(reJust){
            try {
                publisher(yamlMapper.writeValueAsString(returnConfigs));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                throw new RuntimeException("因为奇妙原因 广播 失败");
            }
            // todo  尝试广播 然后回退版本 否则会和版本不一致
        }
        System.out.println("--------------- 打印线程池情况 ---------------");
        System.out.println(threadPoolContext.toString());
        System.out.println("--------------- 打印线程池情况 ---------------");
    }

    public abstract void publisher(String configs);

    private boolean checkUpdateType(ThreadPoolProperty threadPoolProperty, ThreadPoolProperty newConfig) {
//        // 用crc16校验
////        MD5.create().digest(threadPoolProperty.toString()).equals(MD5.create().digest(newConfig.toString()));
//        JSONUtil.toJsonStr(threadPoolProperty).equals(JSONUtil.toJsonStr(newConfig));
        return threadPoolProperty.equals(newConfig);
    }

    /**
     * 动态更新线程池参数（只更新JDK支持动态修改的参数）
     */
    // 1. 现在是监听到了 这个线程池  的类型然后创建对应的线程池 类型
    // 2. 写一个可重写的 线程池 的类型 核心线程 然后还有 最大线程数 还有 任务数

//    {
//        这里任务数要考量  当前是否 消费完成才去剔除还是说是  2.1类似于渐进rehash的方式 2.2还是对于入队列加锁阻塞等待 然后替换queue
//        看看别人怎么写（dymanic tp） 自己再怎么写  ？？？  (直接切换)
//    }
//     3.  定时线程池 还有 非定时线程池  的一个创建 这里有一个想法 就是 用阻塞队列实现入队的阻塞 来实现定时
//


    //  4.  第四个问题 如何 去完成 接管 这个springbean
//    {
//     这里给出两个 方案 一个  使用BeanDefinitionPostProcess
//   {
//     直接对注册的BeanDefinition进行拦截 然后主动创建之后 放入Bean管理也放入 我的外部Map容器进行管理
//

    //   }
//
//    }

//    //当动态配置刷新时，会更新到 Enviroment中，因此这里每隔一秒中从Enviroment中获取配置
    // 修改成 使用环境 变量更新 while（true）
//    String userName = applicationContext.getEnvironment().getProperty("common.name");
//    String userAge = applicationContext.getEnvironment().getProperty("common.age");
//        System.err.println("common name :" + userName + "; age: " + userAge);
//            TimeUnit.SECONDS.sleep(1);
//}
    private void updateThreadPool(String poolName, ThreadPoolProperty newConfig, UPDATE_TYPE updateType) throws Exception {
        if (updateType == UPDATE_TYPE.NO_UPDATE) {
            return;
        }
        if (updateType == UPDATE_TYPE.NEW_LIFE) {
            threadPoolContext.setThreadPoolExecutor(poolName, ThreadPoolUtil.createThreadPoolExecutor(newConfig));
            return;
        }

        if (updateType == UPDATE_TYPE.UPDATE_OLDEST) {
            ThreadPoolExecutor executor = threadPoolContext.getThreadPoolExecutor(poolName);
            // 3.1 调整核心线程数
            int newCoreSize = newConfig.getCorePoolSize();
            if (executor.getCorePoolSize() != newCoreSize) {
                executor.setCorePoolSize(newCoreSize);
                System.out.println("线程池[" + newConfig.getName() + "]核心线程数更新为：" + newCoreSize);
            }

            if (executor.getQueue() instanceof SwiftBlockingQueue /* 这里 不要写泛型否则 无法转化 */ swiftBlockingQueue) {
                boolean swifted = swiftBlockingQueue.swiftQueue(BlockingQueueFactory::<Runnable>createLinkedBlockingQueue, newConfig.getQueueCapacity());
                if(!swifted){
                    throw new Exception("变更驳回");
                }
                System.out.println("线程池[" + newConfig.getName() + "]最大任务数更新为：" + newConfig.getQueueCapacity());
            }

            // 3.2 调整最大线程数
            int newMaxSize = newConfig.getMaxPoolSize();
            if (executor.getMaximumPoolSize() != newMaxSize) {
                executor.setMaximumPoolSize(newMaxSize);
                System.out.println("线程池[" + newConfig.getName() + "]最大线程数更新为：" + newMaxSize);
            }

            // 3.3 调整空闲线程存活时间
            int newKeepAlive = newConfig.getKeepAliveSeconds();
            if (executor.getKeepAliveTime(TimeUnit.SECONDS) != newKeepAlive) {
                executor.setKeepAliveTime(newKeepAlive, TimeUnit.SECONDS);
                System.out.println("线程池[" + newConfig.getName() + "]空闲存活时间更新为：" + newKeepAlive + "秒");
            }

            // 3.4 调整是否允许核心线程超时
            boolean allowTimeout = newConfig.isAllowCoreThreadTimeout();
            if (executor.allowsCoreThreadTimeOut() != allowTimeout) {
                executor.allowCoreThreadTimeOut(allowTimeout);
                System.out.println("线程池[" + newConfig.getName() + "]允许核心线程超时：" + allowTimeout);
            }

            // 3.5 处理线程池启用状态（若禁用则关闭）
            if (!newConfig.isEnabled() && !executor.isShutdown()) {
                executor.shutdown(); // 平缓关闭（不接收新任务，等待现有任务完成）
                System.out.println("线程池[" + newConfig.getName() + "]已禁用并关闭");
            }


            // 注意：拒绝策略（rejectedExecutionHandler）和队列容量（queueCapacity）无法动态修改
            // 若需更新这两个参数，需销毁旧线程池并创建新实例（根据业务场景决定是否支持）
        }
        // 待拓展
    }

    @Override
    public Executor getExecutor() {
//        // 使用专门的线程池处理配置更新（避免阻塞Nacos客户端线程）
//        if(threadPoolContext.getThreadPoolExecutor("commonThreadPool") == null){
//           synchronized (mainLock){
//               if (threadPoolContext.getThreadPoolExecutor("commonThreadPool") == null) {
//                   threadPoolContext.setThreadPoolExecutor("commonThreadPool",ThreadPoolUtil.createThreadPoolExecutor(ThreadPoolProperty.createDefault()));
//               }
//           }
//        }
        return threadPoolContext.getThreadPoolExecutor("commonThreadPool"); // 复用现有线程池或单独定义
    }

    enum UPDATE_TYPE {
        NEW_LIFE(1),
        UPDATE_OLDEST(2),
        NO_UPDATE(3);

        UPDATE_TYPE(int i) {
        }
    }
}
